﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.RobotJog.CApRJSRobotsManager
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.Olp;


namespace DnProcessSimulateCommands.RobotJog;

internal class CApRJSRobotsManager
{
  private static CApRJSRobotsManager _manager;
  private TxRobot _masterRobot;
  private Dictionary<TxRobot, CApRJSingleRobotInfo> _allrobotsInfo;
  private bool _isRobotMasterSlaveMode;
  private Dictionary<TxFrame, TxRobot> _attachedFrameToSlaveRobot;
  private TxPoseData m_masterRobotCurrentPosition;
  private TxOlpControllerUtilities _controllerUtils;
  private bool m_isManipulationSuccessful = true;
  private Dictionary<TxRobot, TxPoseData> _currentPoseForSlaveRobot;

  public event CApRJSRobotsManager.MasterModeChanged OnMasterModeChanged;

  private CApRJSRobotsManager()
  {
    this._allrobotsInfo = new Dictionary<TxRobot, CApRJSingleRobotInfo>();
    this._attachedFrameToSlaveRobot = new Dictionary<TxFrame, TxRobot>();
    this._currentPoseForSlaveRobot = new Dictionary<TxRobot, TxPoseData>();
    this._controllerUtils = new TxOlpControllerUtilities();
  }

  internal Dictionary<TxRobot, CApRJSingleRobotInfo> RobotsInfo
  {
    get => this._allrobotsInfo;
    set => this._allrobotsInfo = value;
  }

  internal TxRobot MasterRobot
  {
    get
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      this._masterRobot = (TxRobot) null;
      foreach (TxRobot key in this._allrobotsInfo.Keys)
      {
        if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo != null && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.MASTER)
        {
          this._masterRobot = key;
          break;
        }
      }
      return this._masterRobot;
    }
  }

  internal int ComboBoxFrameOfReferenceSelectedIndex { get; set; }

  internal bool IsMasterExist()
  {
    bool flag = false;
    foreach (CApRJSingleRobotInfo rjSingleRobotInfo in this._allrobotsInfo.Values)
    {
      if (rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.MASTER)
      {
        flag = true;
        break;
      }
    }
    return flag;
  }

  internal TxObjectList<TxRobot> GetAllRobots()
  {
    TxObjectList<TxRobot> allRobots = new TxObjectList<TxRobot>();
    foreach (TxRobot key in this._allrobotsInfo.Keys)
      ((Collection<TxRobot>) allRobots).Add(key);
    return allRobots;
  }

  internal TxObjectList<TxRobot> GetSlaveRobots()
  {
    TxObjectList<TxRobot> slaveRobots = new TxObjectList<TxRobot>();
    foreach (TxRobot key in this._allrobotsInfo.Keys)
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.SLAVE)
        ((Collection<TxRobot>) slaveRobots).Add(key);
    }
    return slaveRobots;
  }

  internal void AddRobotInfo(TxRobot robot, CApRJSingleRobotInfo currentRobotInfo)
  {
    if (this._allrobotsInfo.ContainsKey(robot))
      this._allrobotsInfo.Remove(robot);
    if (this._allrobotsInfo.ContainsKey(robot))
      return;
    this._allrobotsInfo.Add(robot, currentRobotInfo);
  }

  internal void UpdateRobotInfo(TxRobot robot, CApRJSingleRobotInfo currentRobotInfo)
  {
    this._allrobotsInfo[robot].Framelogic = currentRobotInfo.Framelogic;
    this._allrobotsInfo[robot].IsEnabledRobotPlacement = currentRobotInfo.IsEnabledRobotPlacement;
    this._allrobotsInfo[robot].IsLockConfiguration = currentRobotInfo.IsLockConfiguration;
    this._allrobotsInfo[robot].IsLockedTCPF = currentRobotInfo.IsLockedTCPF;
    this._allrobotsInfo[robot].MasterSlaveRole = currentRobotInfo.MasterSlaveRole;
    this._allrobotsInfo[robot].OriginalFrame = currentRobotInfo.OriginalFrame;
    this._allrobotsInfo[robot].FrameOfRefernceText = currentRobotInfo.FrameOfRefernceText;
    this._allrobotsInfo[robot].FrameOfRefernceTransformation = currentRobotInfo.FrameOfRefernceTransformation;
  }

  internal void UpdateRobotInfo(
    TxRobot robot,
    CApRJFrameOfRefernceInfo currentFrameOfRefernceInfoRobotInfo)
  {
    this._allrobotsInfo[robot].FrameOfRefernceText = currentFrameOfRefernceInfoRobotInfo.FrameOfRefernceText;
    this._allrobotsInfo[robot].FrameOfRefernceTransformation = currentFrameOfRefernceInfoRobotInfo.FrameOfRefernceTransformation;
  }

  internal void UpdateRobotInfoLockConfiguration(TxRobot robot, bool isLockConfiguration)
  {
    this._allrobotsInfo[robot].IsLockConfiguration = isLockConfiguration;
  }

  internal void UpdateRobotInfoLockTCPF(TxRobot robot, bool isLockedTCPF)
  {
    this._allrobotsInfo[robot].IsLockedTCPF = isLockedTCPF;
  }

  internal void UpdateRobotInfoIsEnabledRobotPlacement(TxRobot robot, bool isEnabledRobotPlacement)
  {
    this._allrobotsInfo[robot].IsEnabledRobotPlacement = isEnabledRobotPlacement;
  }

  internal CApRJSingleRobotInfo GetRobotInfo(TxRobot robot)
  {
    CApRJSingleRobotInfo robotInfo = (CApRJSingleRobotInfo) null;
    this._allrobotsInfo.TryGetValue(robot, out robotInfo);
    return robotInfo;
  }

  internal bool CanSetRobotRole(ITxObject robot, RobotMasterSlaveRole role)
  {
    bool flag = true;
    switch (role)
    {
      case RobotMasterSlaveRole.SLAVE:
        if (TxRobot.op_Inequality(this.MasterRobot, (ITxObject) null))
        {
          flag = this.CheckIfSlaveIsAssignmentParentOfMaster(this.MasterRobot, robot as TxRobot);
          break;
        }
        break;
      case RobotMasterSlaveRole.MASTER:
        using (IEnumerator<TxRobot> enumerator = ((Collection<TxRobot>) this.GetSlaveRobots()).GetEnumerator())
        {
          while (enumerator.MoveNext())
          {
            TxRobot current = enumerator.Current;
            flag = this.CheckIfSlaveIsAssignmentParentOfMaster(robot as TxRobot, current);
            if (!flag)
              break;
          }
          break;
        }
    }
    return flag;
  }

  internal void SetRobotsRole(ITxObject robot, RobotMasterSlaveRole role)
  {
    CApRJSingleRobotInfo rjSingleRobotInfo1 = (CApRJSingleRobotInfo) null;
    if (robot == null)
      return;
    try
    {
      this._allrobotsInfo.TryGetValue(robot as TxRobot, out rjSingleRobotInfo1);
    }
    catch (Exception ex)
    {
    }
    if (rjSingleRobotInfo1 == null)
      return;
    if (role == RobotMasterSlaveRole.MASTER)
    {
      foreach (CApRJSingleRobotInfo rjSingleRobotInfo2 in this._allrobotsInfo.Values)
      {
        if (rjSingleRobotInfo1 != rjSingleRobotInfo2 && rjSingleRobotInfo2.MasterSlaveRole == RobotMasterSlaveRole.MASTER)
          rjSingleRobotInfo2.MasterSlaveRole = RobotMasterSlaveRole.NONE;
      }
    }
    if (rjSingleRobotInfo1 == null || rjSingleRobotInfo1.MasterSlaveRole == role)
      return;
    this.RemoveMasterSlaveBehavior();
    rjSingleRobotInfo1.MasterSlaveRole = role;
    this.CreateMasterSlaveBehavior();
  }

  internal void SetMasterSlaveMode(bool isActive)
  {
    bool flag = false;
    if (isActive != this._isRobotMasterSlaveMode)
    {
      this._isRobotMasterSlaveMode = isActive;
      flag = true;
    }
    this.RemoveMasterSlaveBehavior();
    if (this._isRobotMasterSlaveMode && TxRobot.op_Inequality(this.MasterRobot, (ITxObject) null))
      this.CreateMasterSlaveBehavior();
    if (!flag)
      return;
    CApRJSRobotsManager.MasterModeChanged masterModeChanged = this.OnMasterModeChanged;
    if (masterModeChanged == null)
      return;
    masterModeChanged();
  }

  internal bool GetRobotMasterSlaveMode() => this._isRobotMasterSlaveMode;

  internal void CreateMasterSlaveBehavior()
  {
    if (!this._isRobotMasterSlaveMode || !TxRobot.op_Inequality(this.MasterRobot, (ITxObject) null))
      return;
    this.RecordCurrentRobotData();
    foreach (TxRobot key in this._allrobotsInfo.Keys)
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.SLAVE)
        this.CreateMasterSlaveAttachment(key);
    }
  }

  internal void RemoveMasterSlaveBehavior()
  {
    foreach (TxRobot key in this._allrobotsInfo.Keys)
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo != null && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.SLAVE)
        this.RemoveMasterSlaveAttachment(key);
    }
  }

  internal void RecordCurrentRobotData()
  {
    this.m_isManipulationSuccessful = true;
    this.m_masterRobotCurrentPosition = this.MasterRobot.CurrentPose;
  }

  internal bool UpdateSlaveRobots() => this.m_isManipulationSuccessful;

  internal void SaveCurrentPoseForAllSlaveRobots()
  {
    this._currentPoseForSlaveRobot.Clear();
    foreach (TxRobot key in this._allrobotsInfo.Keys)
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.SLAVE)
        this._currentPoseForSlaveRobot.Add(key, key.CurrentPose);
    }
  }

  internal void UpdateCurrentPoseInAllSlaveRobots()
  {
    foreach (TxRobot key in this._allrobotsInfo.Keys)
    {
      CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
      if (this._allrobotsInfo.TryGetValue(key, out rjSingleRobotInfo) && rjSingleRobotInfo.MasterSlaveRole == RobotMasterSlaveRole.SLAVE)
        key.CurrentPose = this._currentPoseForSlaveRobot[key];
    }
  }

  private void RemoveMasterSlaveAttachment(TxRobot slaveRobot)
  {
    if (!TxRobot.op_Inequality(slaveRobot, (ITxObject) null))
      return;
    CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
    this._allrobotsInfo.TryGetValue(slaveRobot, out rjSingleRobotInfo);
    if (rjSingleRobotInfo == null || !TxFrame.op_Inequality(rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot, (ITxObject) null))
      return;
    this._attachedFrameToSlaveRobot.Remove(rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot);
    rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot.AbsoluteLocationChanged -= new TxLocatableObject_AbsoluteLocationChangedEventHandler(this.frame_AbsoluteLocationChanged);
    rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot.Delete();
    rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot = (TxFrame) null;
  }

  private void CreateMasterSlaveAttachment(TxRobot slaveRobot)
  {
    TxFrame frame = this.CreateFrame(slaveRobot);
    if (!this.AttachFrameToMasterTCPF(frame) || !TxRobot.op_Inequality(slaveRobot, (ITxObject) null))
      return;
    CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
    this._allrobotsInfo.TryGetValue(slaveRobot, out rjSingleRobotInfo);
    if (rjSingleRobotInfo == null)
      return;
    rjSingleRobotInfo.AttachmentFrameToFollowMasterRobot = frame;
    frame.AbsoluteLocationChanged += new TxLocatableObject_AbsoluteLocationChangedEventHandler(this.frame_AbsoluteLocationChanged);
    this._attachedFrameToSlaveRobot.Add(frame, slaveRobot);
  }

  private void frame_AbsoluteLocationChanged(
    object sender,
    TxLocatableObject_AbsoluteLocationChangedEventArgs args)
  {
    if (TxUndoTransactionManagerEx.IsObserverRunningInUndoExecution())
      return;
    TxRobot txRobot = (TxRobot) null;
    if (!this._attachedFrameToSlaveRobot.TryGetValue(sender as TxFrame, out txRobot))
      return;
    CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
    if (!this._allrobotsInfo.TryGetValue(txRobot, out rjSingleRobotInfo))
      return;
    this.MasterAttachmentFrameAbsoluteLocationChanged(sender as TxFrame, txRobot);
  }

  private void MasterAttachmentFrameAbsoluteLocationChanged(TxFrame attachFrame, TxRobot slaveRobot)
  {
    if (!this._isRobotMasterSlaveMode || !this.IsMasterExist())
      return;
    CApRJSingleRobotInfo rjSingleRobotInfo = (CApRJSingleRobotInfo) null;
    if (!this._allrobotsInfo.TryGetValue(this.MasterRobot, out rjSingleRobotInfo))
      return;
    bool flag;
    if (!rjSingleRobotInfo.IsLockedTCPF)
    {
      string selectedConfigurationBefore = (string) null;
      if (this._allrobotsInfo[slaveRobot].IsLockConfiguration)
      {
        TxRobotConfigurationData poseConfiguration = slaveRobot.GetPoseConfiguration(slaveRobot.CurrentPose);
        if (poseConfiguration != null)
          selectedConfigurationBefore = this._controllerUtils.GetConfigurationString(poseConfiguration, (ConfigurationStringTypes) 2);
      }
      TxTransformation absoluteLocation = attachFrame.AbsoluteLocation;
      flag = this.SetSlaveTCPFPosition(slaveRobot, absoluteLocation, selectedConfigurationBefore);
      if (!flag && this.m_masterRobotCurrentPosition != null)
        this.MasterRobot.CurrentPose = this.m_masterRobotCurrentPosition;
    }
    else
    {
      string selectedConfigurationBefore = (string) null;
      if (this._allrobotsInfo[slaveRobot].IsLockConfiguration)
      {
        TxRobotConfigurationData poseConfiguration = slaveRobot.GetPoseConfiguration(slaveRobot.CurrentPose);
        if (poseConfiguration != null)
          selectedConfigurationBefore = this._controllerUtils.GetConfigurationString(poseConfiguration, (ConfigurationStringTypes) 2);
      }
      TxTransformation absoluteLocation = attachFrame.AbsoluteLocation;
      flag = this.SetSlaveTCPFPosition(slaveRobot, absoluteLocation, selectedConfigurationBefore);
    }
    this.m_isManipulationSuccessful &= flag;
  }

  private bool SetSlaveTCPFPosition(
    TxRobot robot,
    TxTransformation newTCPFLocation,
    string selectedConfigurationBefore)
  {
    TxRobotInverseData robotInverseData = new TxRobotInverseData(newTCPFLocation, (TxRobotInverseData.TxInverseType) 0);
    return this.SetSlavePose(robot, robot.CalcInverseSolutions(robotInverseData), selectedConfigurationBefore);
  }

  private bool SetSlavePose(
    TxRobot robot,
    ArrayList inverseSolutions,
    string selectedConfigurationBefore)
  {
    if (inverseSolutions != null && inverseSolutions.Count > 0)
    {
      if (selectedConfigurationBefore != null)
      {
        foreach (TxPoseData inverseSolution in inverseSolutions)
        {
          string configurationString = this._controllerUtils.GetConfigurationString(robot.GetPoseConfiguration(inverseSolution), (ConfigurationStringTypes) 2);
          if (!string.IsNullOrEmpty(selectedConfigurationBefore) && configurationString == selectedConfigurationBefore)
          {
            robot.CurrentPose = inverseSolution;
            return true;
          }
        }
      }
      else
      {
        robot.CurrentPose = (TxPoseData) inverseSolutions[0];
        return true;
      }
    }
    return false;
  }

  private TxFrame CreateFrame(TxRobot robot)
  {
    TxFrame frame = TxFrameEx.CreateFrame(new TxFrameCreationDataEx("", robot.TCPF.AbsoluteLocation, true));
    frame.Blank();
    return frame;
  }

  private bool AttachFrameToMasterTCPF(TxFrame attachFrame)
  {
    bool masterTcpf = true;
    if (TxFrame.op_Inequality(attachFrame, (ITxObject) null) && attachFrame.CanAttachTo((ITxLocatableObject) this.MasterRobot.TCPF))
      attachFrame.AttachTo((ITxLocatableObject) this.MasterRobot.TCPF);
    else
      masterTcpf = false;
    return masterTcpf;
  }

  private void DetachFrameToMasterTCPF(TxFrame attachFrame)
  {
    if (!TxFrame.op_Inequality(attachFrame, (ITxObject) null))
      return;
    attachFrame.Detach();
  }

  private bool CheckIfSlaveIsAssignmentParentOfMaster(TxRobot masterRobot, TxRobot slaveRobot)
  {
    return masterRobot.AttachmentParent != slaveRobot && TxEngineeringDataInternal.GetScope((ITxObject) masterRobot.AttachmentParent) != slaveRobot;
  }

  internal void DeleteAllTemporaryFrames()
  {
    foreach (CApRJSingleRobotInfo rjSingleRobotInfo in this._allrobotsInfo.Values)
    {
      if (rjSingleRobotInfo.Framelogic != null)
        rjSingleRobotInfo.Framelogic.Delete();
    }
  }

  internal void Clear()
  {
    this.RemoveMasterSlaveBehavior();
    CApRJSRobotsManager._manager = (CApRJSRobotsManager) null;
  }

  internal static CApRJSRobotsManager the()
  {
    if (CApRJSRobotsManager._manager == null)
      CApRJSRobotsManager._manager = new CApRJSRobotsManager();
    return CApRJSRobotsManager._manager;
  }

  public delegate void MasterModeChanged();
}
